<script lang="ts">
import DustWithdrawalListItemComponent from "$lib/components/model/DustWithdrawalListItemComponent.svelte"
import StakingListItemComponent from "$lib/components/model/StakingListItemComponent.svelte"
import WithdrawalListItemComponent from "$lib/components/model/WithdrawalListItemComponent.svelte"
import Card from "$lib/components/ui/Card.svelte"
import Skeleton from "$lib/components/ui/Skeleton.svelte"
import Tabs from "$lib/components/ui/Tabs.svelte"
import { matchRuntimeResult } from "$lib/utils/snippets.svelte"
import type { Bond, DustWithdrawal, Unbond, Withdrawal } from "@unionlabs/sdk/schema/stake"
import { Array as A, Option as O } from "effect"
import type { Exit } from "effect"

interface Props {
  data: O.Option<
    Exit.Exit<O.Option<readonly (Bond | Unbond | Withdrawal | DustWithdrawal)[]>, unknown>
  >
  walletConnected: boolean
}

let { data, walletConnected }: Props = $props()

type TableFilter = "all" | "bond" | "unbond" | "withdrawal" | "dust"

let tableFilter = $state<TableFilter>("all")
let currentPage = $state<number>(1)

const itemsPerPage = 10

$effect(() => {
  void tableFilter
  currentPage = 1
})
</script>

<style>
.tabs-scroll::-webkit-scrollbar {
  display: none;
}

.tabs-scroll {
  -ms-overflow-style: none;
  scrollbar-width: none;
}
</style>

{#snippet renderBondsTable(
  maybeBonds: O.Option<readonly (Bond | Unbond | Withdrawal | DustWithdrawal)[]>,
)}
  {@const bonds = O.getOrElse(maybeBonds, () => [])}
  {@const filteredBonds = bonds.filter(bond =>
    tableFilter === "all"
    || (tableFilter === "bond" && bond._tag === "Bond")
    || (tableFilter === "unbond" && bond._tag === "Unbond")
    || (tableFilter === "withdrawal" && bond._tag === "Withdrawal")
    || (tableFilter === "dust" && bond._tag === "DustWithdrawal")
  )}
  {@const totalItems = filteredBonds.length}
  {@const totalPages = Math.max(1, Math.ceil(totalItems / itemsPerPage))}
  {@const startIndex = (currentPage - 1) * itemsPerPage}
  {@const endIndex = startIndex + itemsPerPage}
  {@const paginatedBonds = filteredBonds.slice(startIndex, endIndex)}
  {@const hasData = O.isSome(maybeBonds) && filteredBonds.length > 0}

  <div class="relative">
    <div class="px-4 py-2.5 border-b border-zinc-800">
      <div class="flex items-center justify-between gap-2">
        <div class="tabs-scroll flex-1 overflow-x-auto">
          <Tabs
            items={[
              { id: "all", label: "All" },
              { id: "bond", label: "Stakes" },
              { id: "unbond", label: "Unstakes" },
              { id: "withdrawal", label: "Withdrawals" },
              { id: "dust", label: "Dust" },
            ]}
            activeId={tableFilter}
            onTabChange={(id) => tableFilter = id as TableFilter}
          />
        </div>

        {#if hasData}
          <div class="flex gap-0.5 sm:gap-1 flex-shrink-0">
            <button
              onclick={() => currentPage = Math.max(1, currentPage - 1)}
              disabled={currentPage <= 1 || totalPages <= 1}
              class="px-1 sm:px-2 py-1 text-xs sm:text-sm font-medium rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed text-zinc-500 hover:text-zinc-300 w-5 sm:w-8 bg-zinc-900 hover:enabled:bg-zinc-800"
            >
              ←
            </button>
            <div class="px-1.5 sm:px-3 py-1 text-xs sm:text-sm font-medium rounded text-white bg-zinc-800 min-w-[1.5rem] sm:min-w-[3rem] text-center">
              {currentPage}/{totalPages}
            </div>
            <button
              onclick={() => currentPage = Math.min(totalPages, currentPage + 1)}
              disabled={currentPage >= totalPages || totalPages <= 1}
              class="px-1 sm:px-2 py-1 text-xs sm:text-sm font-medium rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed text-zinc-500 hover:text-zinc-300 w-5 sm:w-8 bg-zinc-900 hover:enabled:bg-zinc-800"
            >
              →
            </button>
          </div>
        {/if}
      </div>
    </div>

    <div class="relative overflow-auto">
      {#if hasData}
        {#each paginatedBonds as item}
          {#if item._tag === "Withdrawal"}
            <WithdrawalListItemComponent {item} />
          {:else if item._tag === "DustWithdrawal"}
            <DustWithdrawalListItemComponent {item} />
          {:else}
            <StakingListItemComponent {item} />
          {/if}
        {/each}
      {:else}
        {#each Array(5) as _}
          <div class="p-4 border-b border-zinc-800/50 last:border-b-0">
            <div class="flex items-center justify-between">
              <div class="flex items-center gap-3">
                <Skeleton class="w-8 h-8" />
                <div class="flex flex-col gap-1">
                  <Skeleton class="w-24 h-4" />
                  <Skeleton class="w-16 h-3" />
                </div>
              </div>
              <div class="flex flex-col items-end gap-1">
                <Skeleton class="w-20 h-4" />
                <Skeleton class="w-12 h-3" />
              </div>
            </div>
          </div>
        {/each}

        <div class="absolute inset-0 flex items-center justify-center backdrop-blur-sm bg-zinc-950/60">
          <div class="text-center">
            {#if !walletConnected}
              <div class="text-zinc-400 text-sm font-medium">
                Connect wallet to view history
              </div>
              <div class="text-zinc-500 text-xs mt-1">
                Your staking transactions will appear here
              </div>
            {:else}
              <div class="text-zinc-400 text-sm font-medium">
                No {
                  tableFilter === "all"
                  ? "transactions"
                  : tableFilter === "bond"
                  ? "stakes"
                  : tableFilter === "unbond"
                  ? "unstakes"
                  : tableFilter === "withdrawal"
                  ? "withdrawals"
                  : "dust withdrawals"
                } yet
              </div>
              <div class="text-zinc-500 text-xs mt-1">
                Your staking history will appear here
              </div>
            {/if}
          </div>
        </div>
      {/if}
    </div>
  </div>
{/snippet}

{#snippet renderSkeleton()}
  <div class="relative overflow-auto max-h-72 rounded-lg ring-1 ring-zinc-800/80">
    <table class="w-full text-sm">
      <thead class="sticky top-0 z-10 bg-zinc-950/90">
        <tr class="text-zinc-400 border-b border-zinc-800/80">
          <th class="px-3 py-2 text-left font-semibold tracking-wide text-xs uppercase">arrow</th>
          <th class="px-3 py-2 text-left font-semibold tracking-wide text-xs uppercase">Type</th>
          <th class="px-3 py-2 text-left font-semibold tracking-wide text-xs uppercase">Chain</th>
          <th class="px-3 py-2 text-left font-semibold tracking-wide text-xs uppercase">
            Timestamp
          </th>
          <th class="px-3 py-2 text-right font-semibold tracking-wide text-xs uppercase">Amount</th>
          <th class="px-3 py-2 text-left font-semibold tracking-wide text-xs uppercase">Status</th>
        </tr>
      </thead>
      <tbody>
        {#each Array(10) as _}
          <tr class="even:bg-zinc-900/30 odd:bg-zinc-900/10">
            <td class="px-3 py-2"><div class="h-4 w-24 bg-zinc-700/50 rounded"></div></td>
            <td class="px-3 py-2"><div class="h-4 w-32 bg-zinc-700/50 rounded"></div></td>
            <td class="px-3 py-2 text-right">
              <div class="h-4 w-16 bg-zinc-700/50 rounded ml-auto"></div>
            </td>
            <td class="px-3 py-2"><div class="h-4 w-14 bg-zinc-700/50 rounded"></div></td>
          </tr>
        {/each}
      </tbody>
    </table>
  </div>
{/snippet}

{#snippet renderError(error: any)}
  <pre class="text-red-500 overflow-auto">{JSON.stringify(error, null, 2)}</pre>
{/snippet}

<Card
  class="p-0"
  divided
>
  {#if walletConnected}
    {@render matchRuntimeResult(data, {
      onSuccess: renderBondsTable,
      onFailure: renderError,
      onNone: renderSkeleton,
    })}
  {:else}
    {@render renderBondsTable(O.none())}
  {/if}
</Card>
